package com.ruicar.afs.cloud.product.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.log.annotation.SysLog;
import com.ruicar.afs.cloud.common.core.query.QueryCondition;
import com.ruicar.afs.cloud.common.core.uid.AfsSequenceGenerator;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.product.condition.ProductPlanCondition;
import com.ruicar.afs.cloud.product.condition.ProductPrototypeCondition;
import com.ruicar.afs.cloud.product.condition.ProductTemplateCondition;
import com.ruicar.afs.cloud.product.dto.CheckProductInfoDto;
import com.ruicar.afs.cloud.product.entity.ExtrasProgramInfo;
import com.ruicar.afs.cloud.product.entity.ProductPlan;
import com.ruicar.afs.cloud.product.entity.ProductPlanRate;
import com.ruicar.afs.cloud.product.entity.ProductPlanRepay;
import com.ruicar.afs.cloud.product.enums.*;
import com.ruicar.afs.cloud.product.service.*;
import com.ruicar.afs.cloud.product.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author changyu.gui
 * @version 1.0
 * @date 2020/5/11 20:46
 */
@Slf4j
@RestController
@AllArgsConstructor
@Api("产品原型接口")
@RequestMapping("/productPlan")
public class ProductPlanController {
    private final ProductPlanService productPlanService;
    private final ProductPlanAtomService productPlanAtomService;
    private final ProductTemplateService templateService;
    private final ProductPlanRateService productPlanRateService;
    private final LprConfigurationService lprService;
    private final ProductPlanRepayService productPlanRepayService;
    private final ExtrasProgramService extrasProgramService;
    private final SchemeRiskService planService;
    private final SchemeFinanceService financePlanService;
    private final SchemeLaunchService launchPlanService;
    private final ProductDiscountPlanService productDiscountPlanService;
    private final AfsSequenceGenerator afsSequenceGenerator;

    @RequestMapping(value = "/getPrototypeInfo", method = RequestMethod.GET)
    @ApiOperation(value = "获取产品原型信息数据")
    public IResponse<ProductPlanInfoVo> queryProductPlanList(@ModelAttribute ProductPlanCondition planCondition) {
        ProductPlanInfoVo vo = new ProductPlanInfoVo();
        //获取原子参数值
        Map map = productPlanAtomService.getProductPlanDataInfo(planCondition.getId(), "", SHOW_TYPE_ENUM.PARAMETERS_AFTER_LOAN.getValue());
        vo.setJson(map);
        vo.setRateType((String) map.get("rateType"));//获取利率类型
        vo.setRepaymentType((String) map.get("repaymentType"));//获取还款方式
        vo.setIsAddLoan((String) map.get("isAddLoan"));
        vo.setDiscountType((String) map.get("discountType"));
        vo.setIsRiskPricing((String) map.get("isRiskPricing"));
        map = productPlanAtomService.getProductPlanDataInfo(planCondition.getId(), SHOW_TYPE_ENUM.PARAMETERS_AFTER_LOAN.getValue(), "");
        vo.setPostLoan(map);

        //获取原型基本信息
        ProductPlan plan = productPlanService.getById(planCondition.getId());
        vo.setProductPlan(plan);
        ProductPlanRepay method = productPlanRepayService.getOne(Wrappers.<ProductPlanRepay>query().lambda().eq(ProductPlanRepay::getProductPlanId, plan.getId()), false);
        if (method != null) {
            JSONObject object = JSONObject.parseObject(StringUtils.isEmpty(method.getRepaymentMethodData()) ? "{}" : method.getRepaymentMethodData());
            vo.setMethodParametersForm(object);
        }
        List<ProductPlanRate> list = productPlanRateService.list(Wrappers.<ProductPlanRate>query().lambda()
                .eq(ProductPlanRate::getProductPlanId, planCondition.getId())
        );

        //浮动利率时，利率重新获取
        List<ProductPlanRate> listNew = new ArrayList<>();
        if (AfsEnumUtil.key(StatusType.FLOAT).equals(vo.getRateType())) {
            for (ProductPlanRate productRate : list) {
                Double lprRate = lprService.getLprNew(productRate.getLoanPeriodStart(),productRate.getLoanPeriodEnd());
                productRate.setClearRate(productRate.getAddPointValue().divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(lprRate)));
                productRate.setLpr(new BigDecimal(lprRate));
                listNew.add(productRate);
            }
            list = listNew;
        }

        vo.setPlanRatejson(list);
        return IResponse.success(vo);
    }

    @PostMapping(value = "/queryProductPrototypeList")
    @ApiOperation(value = "多条件分页获取产品原型信息数据")
    public IResponse<List<ProductPrototypeVo>> queryProductPrototypeList(@RequestBody QueryCondition<ProductPlanCondition> planCondition) {
        //创建时间
        String createTimeStart = null;
        String createTimeEnd = null;
        if (planCondition.getCondition().getCreateTimeQuery() != null && planCondition.getCondition().getCreateTimeQuery().length > 0
                && StringUtil.isNotEmpty(planCondition.getCondition().getCreateTimeQuery()[0]) && StringUtil.isNotEmpty(planCondition.getCondition().getCreateTimeQuery()[1])) {
            createTimeStart = planCondition.getCondition().getCreateTimeQuery()[0] ;
            createTimeEnd = planCondition.getCondition().getCreateTimeQuery()[1] ;
        }
        planCondition.getCondition().setCreateTimeStart(createTimeStart);
        planCondition.getCondition().setCreateTimeEnd(createTimeEnd);
        planCondition.getCondition().setIsModel(AfsEnumUtil.key(StatusEnum.YES));
        IPage<ProductPrototypeVo> list = productPlanService.queryProductPrototypeList(new Page(planCondition.getPageNumber(), planCondition.getPageSize()), planCondition.getCondition());
        return IResponse.success(list);
    }

    @PostMapping(value = "/queryProductProposalList")
    @ApiOperation(value = "多条件分页获取产品方案信息数据")
    public IResponse<List<ProductPrototypeVo>> queryProductProposalList(@RequestBody QueryCondition<ProductPlanCondition> planCondition) {
        //创建时间
        String createTimeStart = null;
        String createTimeEnd = null;
        if (planCondition.getCondition().getCreateTimeQuery() != null && planCondition.getCondition().getCreateTimeQuery().length > 0
                && StringUtil.isNotEmpty(planCondition.getCondition().getCreateTimeQuery()[0]) && StringUtil.isNotEmpty(planCondition.getCondition().getCreateTimeQuery()[1])) {
            createTimeStart = planCondition.getCondition().getCreateTimeQuery()[0] ;
            createTimeEnd = planCondition.getCondition().getCreateTimeQuery()[1] ;
        }
        planCondition.getCondition().setCreateTimeStart(createTimeStart);
        planCondition.getCondition().setCreateTimeEnd(createTimeEnd);
        planCondition.getCondition().setIsModel(AfsEnumUtil.key(StatusEnum.NO));
        IPage<ProductPrototypeVo> list = productPlanService.queryProductPrototypeList(new Page(planCondition.getPageNumber(), planCondition.getPageSize()), planCondition.getCondition());
        return IResponse.success(list);
    }

    @PostMapping("/temporaryStorage")
    @ApiOperation(value = "暂存产品原型")
    @SysLog("暂存产品原型")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<ProductPlan> temporaryStorage(@RequestBody ProductPrototypeCondition prototypeCondition) {
        prototypeCondition.getProductPlan().setIsModel(AfsEnumUtil.key(StatusEnum.YES));
        prototypeCondition.getProductPlan().setStatus(AfsEnumUtil.key(ProductPrototypeStatus.TEMPORARY_STORAGE));
        productPlanService.saveOrUpdate(prototypeCondition);
        return new IResponse<ProductPlan>().setData(prototypeCondition.getProductPlan());
    }

    @PostMapping("/savePrototype")
    @ApiOperation(value = "保存产品原型")
    @SysLog("保存产品原型")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<ProductPlan> savePrototype(@RequestBody ProductPrototypeCondition prototypeCondition) {
        prototypeCondition.getProductPlan().setIsModel(AfsEnumUtil.key(StatusEnum.YES));
        prototypeCondition.getProductPlan().setStatus(AfsEnumUtil.key(ProductPrototypeStatus.INVALID));
        productPlanService.saveOrUpdate(prototypeCondition);
        return new IResponse<ProductPlan>().setData(prototypeCondition.getProductPlan());
    }

    @PostMapping("/temporaryStorageProposal")
    @ApiOperation(value = "暂存产品方案")
    @SysLog("暂存产品方案")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<ProductPlan> temporaryStorageProposal(@RequestBody ProductPrototypeCondition prototypeCondition) {
        prototypeCondition.getProductPlan().setIsModel(AfsEnumUtil.key(StatusEnum.NO));
        prototypeCondition.getProductPlan().setStatus(AfsEnumUtil.key(ProductOnlineStatus.TEMPORARY_STORAGE));
        productPlanService.saveOrUpdate(prototypeCondition);
        return new IResponse<ProductPlan>().setData(prototypeCondition.getProductPlan());
    }

    @PostMapping("/saveProductProposal")
    @ApiOperation(value = "保存产品方案")
    @SysLog("保存产品方案")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<ProductPlan> saveProductProposal(@RequestBody ProductPrototypeCondition prototypeCondition) {
        prototypeCondition.getProductPlan().setIsModel(AfsEnumUtil.key(StatusEnum.NO));
        prototypeCondition.getProductPlan().setStatus(AfsEnumUtil.key(ProductOnlineStatus.TAKE_EFFECT));
        productPlanService.saveOrUpdate(prototypeCondition);
        return new IResponse<ProductPlan>().setData(prototypeCondition.getProductPlan());
    }

    @PostMapping("/getVueInfo")
    @ApiOperation(value = "获取vue信息")
    public IResponse<VueVo> getVueInfo(@RequestBody ProductPlanCondition planCondition) {
        Map<String, List<VueJs>> map = new HashMap<>();
        List<ProductPlanVo> list = productPlanService.getVueInfo(planCondition);
        list.stream().forEach(
                productPlanVo -> {
                    List<VueJs> vueJsList = new ArrayList<>();
                    String atomShowType = productPlanVo.getAtomShowType();

                    //是否必输不为空时，手动设定必输
                    if(planCondition.getIsRequire()!=null){
                        productPlanVo.setRequire(planCondition.getIsRequire());
                    }

                    VueJs js = new VueJs(productPlanVo);
                    if (map.containsKey(atomShowType)) {
                        vueJsList = map.get(atomShowType);
                        vueJsList.add(js);
                    } else {
                        vueJsList.add(js);
                        map.put(atomShowType, vueJsList);
                    }
                });
        VueVo vueVo = new VueVo(map);
        return new IResponse<VueVo>().setData(vueVo);
    }

    @RequestMapping(value = "/effective", method = RequestMethod.POST)
    @ApiOperation(value = "设置产品原型有效")
    @SysLog("设置产品原型有效")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Boolean> effective(@ModelAttribute ProductTemplateCondition productTemplateCondition) {
        List<ProductPlan> list = productPlanService.listByIds(Arrays.asList(productTemplateCondition.getIds()));
        List<ProductPlan> planList = new ArrayList<>();
        for (ProductPlan plan : list) {
            if (AfsEnumUtil.key(ProductPrototypeStatus.INVALID).equals(plan.getStatus())) {
                plan.setStatus(AfsEnumUtil.key(ProductPrototypeStatus.TAKE_EFFECT));
                planList.add(plan);
            } else if (AfsEnumUtil.key(ProductPrototypeStatus.TEMPORARY_STORAGE).equals(plan.getStatus())) {
                return IResponse.fail("暂存不可设置有效");
            }
        }
        if (planList.size() > 0) productPlanService.updateBatchById(planList);
        return new IResponse<Boolean>().setData(true).setMsg("批量通过id设置数据有效成功");
    }

    @PostMapping("/invalid")
    @ApiOperation(value = "设置产品原型无效")
    @SysLog("设置产品原型无效")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Boolean> invalid(@ModelAttribute ProductTemplateCondition productTemplateCondition) {
        List<ProductPlan> list = productPlanService.listByIds(Arrays.asList(productTemplateCondition.getIds()));
        List<ProductPlan> planList = new ArrayList<>();
        for (ProductPlan plan : list) {

            List<ProductPlan> listProductPrototype = productPlanService.list(Wrappers.<ProductPlan>query().lambda()
                    .eq(ProductPlan::getIsModel, AfsEnumUtil.key(StatusEnum.NO))
                    .eq(ProductPlan::getProductPrototypeId, plan.getId())
            );
            if (listProductPrototype.size() > 0)
                return IResponse.fail("原型【"+plan.getProductName()+"】被上线产品使用不可设置无效！");

            if (plan != null && AfsEnumUtil.key(ProductPrototypeStatus.TAKE_EFFECT).equals(plan.getStatus())) {
                plan.setStatus(AfsEnumUtil.key(ProductPrototypeStatus.INVALID));
                planList.add(plan);
            } else if (AfsEnumUtil.key(ProductPrototypeStatus.TEMPORARY_STORAGE).equals(plan.getStatus())) {
                return IResponse.fail("暂存不可设置无效！");
            }
        }
        if (planList.size() > 0) productPlanService.updateBatchById(planList);
        return new IResponse<Boolean>().setData(true).setMsg("批量通过id设置数据无效成功");
    }

    @PostMapping("/copyPrototype")
    @SysLog("复制产品原型或方案")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Boolean> copyPrototype(@ModelAttribute ProductPlanCondition planCondition) {
        //查询原产品
        ProductPlan productPlan = productPlanService.getById(planCondition.getId());
        //判断是否存在
        if (productPlan == null)
            return IResponse.fail("产品不存在!");

        //编号处理
        if(StringUtils.isEmpty(planCondition.getProductNumber())){
            //获取编号
            String planNo = null;
            if(AfsEnumUtil.key(TemplateCategory.Father).equals(productPlan.getTemplateCategory()) && AfsEnumUtil.key(StatusEnum.YES).equals(productPlan.getIsModel())){
                Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_YX), StatusType.PRODUCT_NUM_YX.toString());
                planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_YX) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
            }else if(AfsEnumUtil.key(TemplateCategory.Son).equals(productPlan.getTemplateCategory()) && AfsEnumUtil.key(StatusEnum.YES).equals(productPlan.getIsModel())){
                Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_YXS), StatusType.PRODUCT_NUM_YXS.toString());
                planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_YXS) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
            }else if(AfsEnumUtil.key(TemplateCategory.Father).equals(productPlan.getTemplateCategory()) && AfsEnumUtil.key(StatusEnum.NO).equals(productPlan.getIsModel())){
                Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_PD), StatusType.PRODUCT_NUM_PD.toString());
                planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_PD) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
            }else if(AfsEnumUtil.key(TemplateCategory.Son).equals(productPlan.getTemplateCategory()) && AfsEnumUtil.key(StatusEnum.NO).equals(productPlan.getIsModel())){
                Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_PDS), StatusType.PRODUCT_NUM_PDS.toString());
                planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_PDS) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
            }
            productPlan.setProductNumber(planNo);
        }else{
            productPlan.setProductNumber(planCondition.getProductNumber());
        }

        int count = productPlanService.count(Wrappers.<ProductPlan>query().lambda()
                .eq(ProductPlan::getProductNumber, planCondition.getProductNumber())
                .eq(ProductPlan::getIsModel,productPlan.getIsModel())
        );
        if (count > 0)
            return IResponse.fail("编号已存在!");
        count = productPlanService.count(Wrappers.<ProductPlan>query().lambda()
                .eq(ProductPlan::getProductName, planCondition.getProductName())
                .eq(ProductPlan::getIsModel,productPlan.getIsModel())
        );
        if (count > 0)
            return IResponse.fail("名称已存在!");
        //进行方案复制
        productPlan = new ProductPlan(productPlan);
        productPlan.setProductName(planCondition.getProductName());
        productPlan.setStatus(AfsEnumUtil.key(ProductPrototypeStatus.TEMPORARY_STORAGE));
        productPlanService.save(productPlan);
        //复制产品原子
        productPlanAtomService.copyProductPlanData(productPlan.getId(), planCondition.getId());
        //复制产品利率
        productPlanRateService.copyProductPlanRate(productPlan.getId(), planCondition.getId());
        //复制产品还款方式信息
        ProductPlanRepay method = productPlanRepayService.getOne(Wrappers.<ProductPlanRepay>query().lambda()
                .eq(ProductPlanRepay::getProductPlanId, planCondition.getId())
                , false
        );
        if (method != null) {
            method.setProductPlanId(productPlan.getId());
            method = new ProductPlanRepay(method);
            productPlanRepayService.save(method);
        }
        return new IResponse<Boolean>().setData(true).setMsg("复制成功");
    }

    @PostMapping(value = "/getProductPlanListByLaunch", consumes = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "进件查询投放的产品")
    public IResponse<ProductPlan> getProductPlanListByLaunch(@RequestBody CheckProductInfoDto info) {
        IPage<ProductPlan> list = productPlanService.getProductPlanListByLaunch(info);
        return IResponse.success(list);
    }

    @PostMapping(value = "/getProductDetails")
    @ApiOperation(value = "根据产品ID查询产品详情")
    public IResponse<Map> getProductDetails(@RequestBody CheckProductInfoDto info) {
        Map map = productPlanService.getProductDetails(info);
        return IResponse.success(map);
    }

    @PostMapping(value = "/checkProductInfo")
    @ApiOperation(value = "产品信息融资校验")
    public IResponse<List> checkProductInfo(@RequestBody CheckProductInfoDto info) {
        List<String> result = productPlanService.checkProductInfo(info);
        if (result.size() > 0) {
            return IResponse.fail(result.toString());
        } else {
            return IResponse.success(result);
        }
    }

    @PostMapping(value = "/chenkRiskInfo")
    @ApiOperation(value = "产品信息风控准入校验")
    public IResponse<List> chenkRiskInfo(@RequestBody CheckProductInfoDto info) {
        List<String> result = productPlanService.chenkRiskInfo(info);
        if (result.size() > 0) {
            return IResponse.fail(result.toString());
        } else {
            return IResponse.success(result);
        }
    }

    @PostMapping(value = "/getProductPlanDataByProductId")
    @ApiOperation(value = "根据产品ID查询产品贷后参数")
    public IResponse getProductPlanDataByProductId(@RequestBody CheckProductInfoDto info) {
        List<ProductPlanDataVo> list = productPlanAtomService.getProductPlanDataByProductId(info.getId(), null);
        return IResponse.success(list);
    }

    @PostMapping(value = "/getcustomerrate")
    @ApiOperation(value = "查询产品利率")
    public IResponse<JSONObject> getcustomerrate(@RequestBody CheckProductInfoDto info) {
        JSONObject result = productPlanService.getcustomerrate(info);
        return IResponse.success(result);
    }

    @PostMapping("/updateStatus")
    @SysLog("修改子产品状态")
    public IResponse updateStatus(@ModelAttribute ProductPlanCondition planCondition) {
        //查询原产品
        ProductPlan productPlan = productPlanService.getById(planCondition.getId());
        //后台状态为暂存
        if(AfsEnumUtil.key(ProductOnlineStatus.TEMPORARY_STORAGE).equals(productPlan.getStatus())){
            return IResponse.fail("先保存子产品信息！");
        }
        //前端状态=生效  &&  后台状态为上线
        if(AfsEnumUtil.key(ProductOnlineStatus.TAKE_EFFECT).equals(planCondition.getStatusType()) && AfsEnumUtil.key(ProductOnlineStatus.GO_ONLINE).equals(productPlan.getStatus())){
            int count = extrasProgramService.count(Wrappers.<ExtrasProgramInfo>query().lambda()
                    .eq(ExtrasProgramInfo::getStatus, AfsEnumUtil.key(StatusEnum.YES))
                    .eq(ExtrasProgramInfo::getProductPlanId, productPlan.getId())
            );
            if (count > 0){
                return IResponse.fail("已经被生效的附加方案使用，不可设置生效状态！");
            }
        }
        //设置状态
        productPlan.setStatus(planCondition.getStatusType());
        productPlanService.updateById(productPlan);
        return IResponse.success("状态设置成功！");
    }


}
